package jrain.fw.sql.parser;

import jrain.fw.sql.parser.expr.IfExpression;
import jrain.fw.sql.parser.expr.RootExpression;
import jrain.fw.sql.parser.expr.SqlExpression;
import jrain.fw.sql.parser.expr.SubSqlExpression;
import jrain.fw.sql.parser.expr.VarExpression;
import jrain.utils.ch.CharUtils;

public class ELSqlParser {

	public static void main(String[] args) {
		ELSqlParser parser = new ELSqlParser();
		String sql = "if(a){}else if(b){ if(b1){}else{}  }else if(c){}else{}";
		SqlExpression expression = parser.parser(sql);
		System.out.println(expression.calcSql());
	}

	public SqlExpression parser(String sql) {
		return parserSql(sql);

	}

	public RootExpression parserSql(String sql) {
		RootExpression expression = new RootExpression();
		int preIndex = 0;
		int sqlLength = sql.length();
		for (int index = 0; index < sql.length(); index++) {
			String match = "${";
			int tempIndex = index + 2;
			if (tempIndex <= sqlLength) {
				String tempChar = sql.substring(index, index + 2);
				if (match.equals(tempChar)) {
					// 基础SQL
					if (index > preIndex) {
						String subSql = sql.substring(preIndex, index);
						SubSqlExpression sqlExpression = new SubSqlExpression();
						sqlExpression.setSubSql(subSql);
						expression.addExpression(sqlExpression);
						preIndex = index;
					}
					ELParseBean bean = parserVar(sql, index);
					index = bean.getIndex();
					preIndex = index;
					// 因为 for循环会自动加1
					index = index - 1;
					expression.addExpression(bean.getExpression());
					continue;

				}
			}
			char ch = sql.charAt(index);
			if (CharUtils.isWhitespace(ch)) {
				match = "if(";
				tempIndex = index + 4;
				if (tempIndex <= sqlLength) {
					String tempChar = sql.substring(index + 1, tempIndex);
					if (match.equals(tempChar)) {
						// 基础SQL
						if (index > preIndex) {
							String subSql = sql.substring(preIndex, index);
							SubSqlExpression sqlExpression = new SubSqlExpression();
							sqlExpression.setSubSql(subSql);
							expression.addExpression(sqlExpression);
							preIndex = index;
						}
						ELParseBean bean = parserIf(sql, index + 1);
						index = bean.getIndex();
						preIndex = index;
						// 因为 for循环会自动加1
						index = index - 1;
						expression.addExpression(bean.getExpression());
						continue;
					}
				}
			}
			if (index == 0 && ch == 'i') {
				if (sql.startsWith("if(")) {
					ELParseBean bean = parserIf(sql, 0);
					index = bean.getIndex();
					preIndex = index;
					// 因为 for循环会自动加1
					index = index - 1;
					expression.addExpression(bean.getExpression());
					continue;
				}
			}

		}
		if (sqlLength > preIndex) {
			String subSql = sql.substring(preIndex, sqlLength);
			SubSqlExpression sqlExpression = new SubSqlExpression();
			sqlExpression.setSubSql(subSql);
			expression.addExpression(sqlExpression);
		}
		return expression;
	}

	protected ELParseBean parserVar(String sql, int index) {
		ELParseBean parseBean = new ELParseBean();
		int oldInIndex = index;
		index = index + 2;
		assertVarErrorLength(index < sql.length());
		String tempVar = sql.substring(oldInIndex, index);
		if (!"${".equals(tempVar)) {
			paserVarError(tempVar);
		}
		// 跳过空白
		index = skip(sql, index);
		assertVarErrorLength(index < sql.length());
		StringBuilder sb = new StringBuilder();
		// 匹配第一个字符
		char ch = sql.charAt(index++);
		if (CharUtils.isVarFirst(ch)) {
			sb.append(ch);
			// 匹配更多字符
			while (index < sql.length()) {
				ch = sql.charAt(index);
				if (CharUtils.isVar(ch)) {
					sb.append(ch);
					index++;
				} else {
					break;
				}
			}
			assertVarErrorLength(index < sql.length());
			// 跳过空白
			index = skip(sql, index);
			assertVarErrorLength(index < sql.length());
			ch = sql.charAt(index++);
			if (ch == '}') {
				VarExpression varExpression = new VarExpression();
				varExpression.setVar(sb.toString());
				parseBean.setExpression(varExpression);
				parseBean.setIndex(index);
			} else {
				String msg = sql.substring(oldInIndex, index);
				paserVarError(msg);
			}
		} else {
			String msg = sql.substring(oldInIndex, index);
			paserVarError(msg);
		}
		return parseBean;
	}

	protected void assertVarErrorLength(boolean b) {
		if (!b) {
			throw new ParserException("variable expression parsing error!");
		}
	}

	protected void paserVarError(String msg) {
		throw new ParserException("variable expression parsing error! msg=" + msg);
	}

	protected ELParseBean parserIf(String sql, int index) {
		ELParseBean parseBean = new ELParseBean();
		int oldInIndex = index;
		index = index + 3;
		assertVarErrorLength(index < sql.length());
		String tempBean = sql.substring(oldInIndex, index);
		if (!"if(".equals(tempBean)) {
			paserIfError(tempBean);
		}
		IfExpression ifExpression = new IfExpression();
		parseBean.setExpression(ifExpression);

		// 匹配条件开始============
		int pointAInex = index;
		int pointACounter = 0;
		char ch = ' ';
		while (index < sql.length()) {
			ch = sql.charAt(index);
			if (ch == '(') {
				pointACounter++;

			} else if (ch == ')') {
				if (pointACounter == 0) {
					break;
				} else {
					pointACounter--;
				}
			}
			index++;
		}
		assertIfErrorLength(index < sql.length());
		String condition = sql.substring(pointAInex, index);
		if (ch == ')') {
			ifExpression.setCondition(condition);
		} else {
			paserIfError(condition);
		}
		index++;
		// 匹配条件结束============
		// 跳过空白
		index = skip(sql, index);
		assertIfErrorLength(index < sql.length());
		// 匹配IF内容开始============
		ch = sql.charAt(index++);
		assertIfErrorLength(ch == '{');
		int pointBInext = index;
		int pointBCounter = 0;
		// 向后搜索到}
		while (index < sql.length()) {
			ch = sql.charAt(index);
			if (ch == '{') {
				pointBCounter++;

			} else if (ch == '}') {
				if (pointBCounter == 0) {
					break;
				} else {
					pointBCounter--;
				}
			}
			index++;
		}
		String ifSubSql = sql.substring(pointBInext, index);
		if (ch == '}') {
			// 匹配SQL
			RootExpression rootExpression = parserSql(ifSubSql);
			ifExpression.setIfExpr(rootExpression);
		} else {
			paserIfError(ifSubSql);
		}
		index++;
		// 匹配IF内容结束============

		ELParseBean elseBean = parserElse(sql, index);
		ifExpression.setElseExpr(elseBean.getExpression());
		parseBean.setIndex(elseBean.getIndex());
		return parseBean;
	}

	protected ELParseBean parserElse(String sql, int index) {
		index = skip(sql, index);
		ELParseBean parseBean = new ELParseBean();
		parseBean.setIndex(index);
		// 尝试搜索else
		if (index + 4 < sql.length() && "else".equals(sql.substring(index, index + 4))) {
			index = index + 4;
			int bindex = index;
			index = skip(sql, bindex);
			boolean bspace = index > bindex;
			assertIfErrorLength(index < sql.length());
			char ch = sql.charAt(index);
			// else 模块
			if (ch == '{') {
				index++;
				int pointInex = index;
				int pointCounter = 0;
				// 向后搜索到}
				while (index < sql.length()) {
					ch = sql.charAt(index);
					if (ch == '{') {
						pointCounter++;

					} else if (ch == '}') {
						if (pointCounter == 0) {
							break;
						} else {
							pointCounter--;
						}
					}
					index++;
				}

				String ifSubSql = sql.substring(pointInex, index);
				if (ch == '}') {
					// 匹配SQL
					RootExpression rootExpression = parserSql(ifSubSql);
					parseBean.setExpression(rootExpression);
				} else {
					paserIfError(ifSubSql);
				}
				index++;
				parseBean.setIndex(index);
			}
			// else if 模块
			else if (bspace && ch == 'i') {
				ELParseBean tempBean = parserIf(sql, index);
				parseBean.setExpression(tempBean.getExpression());
				parseBean.setIndex(tempBean.getIndex());

			} else {
				paserIfError("Illegal else module");
			}
		}
		return parseBean;
	}

	protected void assertIfErrorLength(boolean b) {
		if (!b) {
			throw new ParserException("if expression parsing error!");
		}
	}

	protected void paserIfError(String msg) {
		throw new ParserException("if expression parsing error! msg=" + msg);
	}

	protected int skip(String sql, int index) {
		while (index < sql.length()) {
			char ch = sql.charAt(index);
			if (CharUtils.isWhitespace(ch)) {
				index = index + 1;
			} else {
				break;
			}
		}
		return index;
	}
}
